/**
 * 
 */
package org.tio.im.common;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.core.GroupContext;
import org.tio.im.common.cache.caffeineredis.CaffeineRedisCacheManager;
import org.tio.im.common.cache.redis.JedisTemplate;
import org.tio.im.common.packets.ChatBody;
import org.tio.im.common.packets.Client;
import org.tio.im.common.packets.Command;
import org.tio.im.common.packets.RespBody;
import org.tio.im.common.packets.User;
import org.tio.im.common.utils.Coast;
import org.tio.im.common.utils.ImKit;
import org.tio.utils.lock.SetWithLock;

import com.alibaba.fastjson.JSON;

import cn.hutool.core.bean.BeanUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 版本: [1.0]
 * 功能说明: 
 * 作者: WChao 创建时间: 2017年9月22日 上午9:07:18
 */
public class ImAio {
	private static Logger log = LoggerFactory.getLogger(ImAio.class);
	/**
	 * 功能描述：[根据用户ID获取当前用户]
	 * 创建者：WChao 创建时间: 2017年9月18日 下午4:34:39
	 * @param groupContext
	 * @param userid
	 * @return
	 */
	public static List<User> getUser(GroupContext groupContext,String userid){
		SetWithLock<ChannelContext> channelContexts = ImAio.getChannelContextsByUserid(groupContext, userid);
		if(channelContexts != null && !channelContexts.getObj().isEmpty()){
			List<User> users = new ArrayList<User>();
			for(ChannelContext channelContext : channelContexts.getObj()){
				ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute();
				Client client = imSessionContext.getClient();
				users.add(client.getUser());
			}
			return users;
		}
		return null;
	}
	/**
	 * 
		 * 功能描述：[根据用户ID获取当前用户所在通道集合]
		 * 创建者：WChao 创建时间: 2017年9月18日 下午4:34:39
		 * @param groupContext
		 * @param userid
		 * @return
		 *
	 */
	public static SetWithLock<ChannelContext> getChannelContextsByUserid(GroupContext groupContext,String userid){
		SetWithLock<ChannelContext> channelContexts = Aio.getChannelContextsByUserid(groupContext, userid);
		return channelContexts;
	}
	/**
	 * 
		 * 功能描述：[获取所有用户(在线+离线)]
		 * 创建者：WChao 创建时间: 2017年9月18日 下午4:31:54
		 * @param groupContext
		 * @return
		 *
	 */
	public static List<User> getAllUser(GroupContext groupContext){
		List<User> users = new ArrayList<User>();
		Set<ChannelContext> userChannels = Aio.getAllChannelContexts(groupContext).getObj();
		if(userChannels == null)
			return users;
		for(ChannelContext channelContext : userChannels){
			ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute();
			Client client = imSessionContext.getClient();
			if(client != null && client.getUser() != null){
				User user = new User();
				BeanUtil.copyProperties(client.getUser(), user,"friends","groups");
				users.add(user);
			}
		}
		return users;
	}
	/**
	 * 
		 * 功能描述：[获取所有在线用户]
		 * 创建者：WChao 创建时间: 2017年9月18日 下午4:31:42
		 * @param groupContext
		 * @return
		 *
	 */
	public static List<User> getAllOnlineUser(GroupContext groupContext){
		List<User> users = new ArrayList<User>();
		Set<ChannelContext> userChannels = Aio.getAllConnectedsChannelContexts(groupContext).getObj();
		if(userChannels == null)
			return users;
		for(ChannelContext channelContext : userChannels){
			ImSessionContext imSessionContext = (ImSessionContext)channelContext.getAttribute();
			if(imSessionContext != null){
				Client client = imSessionContext.getClient();
				if(client != null && client.getUser() != null){
					User user = new User();
					BeanUtil.copyProperties(client.getUser(), user,"friends","groups");
					users.add(user);
				}
			}
		}
		return users;
	}
	
	/**
	 * 功能描述：[发送到群组(所有不同协议端)]
	 * 创建者：WChao 创建时间: 2017年9月21日 下午3:26:57
	 * @param groupContext
	 * @param group
	 * @param packet
	 */
	public static void sendToGroup(GroupContext groupContext, String group, ImPacket packet){
		if(packet.getBody() == null)
			return;
		SetWithLock<ChannelContext> withLockChannels = Aio.getChannelContextsByGroup(groupContext, group);
		if(withLockChannels == null)
			return;
		ReadLock readLock = withLockChannels.getLock().readLock();
		readLock.lock();
		try{
			Set<ChannelContext> channels = withLockChannels.getObj();
			if(channels != null && channels.size() > 0){
				for(ChannelContext channelContext : channels){
					send(channelContext,packet);
				}
			}
		}finally{
			readLock.unlock();
		}
	}
	/**
	 * 发送到指定通道(一个账号多通道);
	 * @param toChannleContexts
	 * @param packet
	 */
	public static void send(SetWithLock<ChannelContext> toChannleContexts,ImPacket packet){
		if(toChannleContexts == null || toChannleContexts.size() < 1)
			return;
		ReadLock readLock = toChannleContexts.getLock().readLock();
		readLock.lock();
		try{
			Set<ChannelContext> channels = toChannleContexts.getObj();
			if(channels.size() > 0){
				for(ChannelContext channelContext : channels){
					send(channelContext, packet);
				}
			}
		}finally{
			readLock.unlock();
		}
	}
	/**
	 * 发送到指定通道;
	 * @param toChannleContexts
	 * @param packet
	 */
	public static void send(ChannelContext channelContext,ImPacket packet){
		if(channelContext == null)
			return;
		ImPacket rspPacket = ImKit.ConvertRespPacket(packet.getBody(), packet.getCommand(), channelContext);
		rspPacket.setSynSeq(packet.getSynSeq());
		Aio.sendToId(channelContext.getGroupContext(), channelContext.getId(), rspPacket);
	}
	
	
	
	/**
	 * 
	 * 功能描述：[发送到群组(所有不同协议端)] 创建者：WChao 创建时间: 2017年9月21日 下午3:26:57
	 * 
	 * @param groupContext
	 * @param group
	 * @param packet
	 *
	 */
	public static void sendToGroupExpectSelf(ChannelContext orignChannelContext, String group, ImPacket packet,ImPacket selfPacket) {
		if (packet.getBody() == null)
			return;
		GroupContext groupContext = orignChannelContext.getGroupContext();
		SetWithLock<ChannelContext> withLockChannels = Aio.getChannelContextsByGroup(groupContext, group);
		if (withLockChannels == null)
			return;
		Set<ChannelContext> channels = withLockChannels.getObj();
		if (channels.size() > 0) {
			String id = orignChannelContext.getId();
			for (ChannelContext channelContext : channels) {
				if (id.equals(channelContext.getId())) {
					send(channelContext, selfPacket);
				}else {
					send(channelContext, packet);
				}
			}
		}
	}
	
	
	
	

	/**
	 * 
	 * 功能描述：[发送到群组(所有不同协议端)]--向商家发送 创建者：WChao 创建时间: 2017年9月21日 下午3:26:57
	 * 
	 * @param groupContext
	 * @param group
	 * @param userId
	 *            用户id
	 * @param packet
	 *
	 */
	public static void sendToShopGroup(ChannelContext orignChannelContext, String group, String userId,
			ChatBody chatBody) {
		GroupContext groupContext = orignChannelContext.getGroupContext();
		// 判断发送的用户是不是存在
		SetWithLock<ChannelContext> channelContextsByUserid = Aio.getChannelContextsByUserid(groupContext, userId);
		if (channelContextsByUserid != null && channelContextsByUserid.size() > 0) {
			/**
			 * 设置多用户，我只要一个用户就行
			 */
			Set<ChannelContext> toChannleContexts = channelContextsByUserid.getObj();
			ChannelContext sendUser = null; 
			for (ChannelContext channelContext : toChannleContexts) {
				sendUser = channelContext;
				break;
			}
			log.info("用户不等于空user:" + userId);
			// 判断该组是不是有用户
			SetWithLock<ChannelContext> withLockChannels = Aio.getChannelContextsByGroup(groupContext, group);
			if (withLockChannels == null) {
				log.info("商家group:" + group+"没有用户");
				return;
			}		
			Set<ChannelContext> channels = withLockChannels.getObj();
			if (channels.size() == 0) {
				log.info("channels用户数量0,"+"商家group:" + group);
				return;
			}
			log.info("channels用户数量:" + channels.size()+",商家group:" + group);
			ImSessionContext imSessionContext = (ImSessionContext) sendUser.getAttribute();
			User user = imSessionContext.getClient().getUser();

			chatBody.setNickName(user.getNickName());
			chatBody.setShopId(Long.parseLong(group));
			chatBody.setUserId(Long.parseLong(user.getId()));
			chatBody.setGender(user.getGender());
			chatBody.setPhoto(user.getPhoto());
			chatBody.setAge(user.getAge());
			chatBody.setType(null);					
			//log.info("聊天信息：" + chatBody.toString());
			// 设置消息类型
			Command commandChatReq = Command.COMMAND_CHAT_REQ;
			chatBody.setCmd(commandChatReq.getNumber());
			// 判断是否测试
			boolean exam = user.getYwScore() != null ? true : false;
			
			//chatBody.getUserId()
			Long userId2 = Long.parseLong(userId) ;
			Long moduleId2 = chatBody.getModuleId();
			//发梨的用户是否在线
			boolean existsSendPearUser = false;
			User channelUser = null;
			ImSessionContext userContext = null;
			// 已测试
			if (exam) {

				int ywScore = user.getYwScore();
				int qgScore = user.getQgScore();
				int xnScore = user.getXnScore();
				int yzScore = user.getYzScore();
				int mlScore = user.getMlScore();
				Double charm = user.getCharm();
				String compreAttr = user.getCompreAttr();
				int gender = user.getGender();
				int matching = 0;
				for (ChannelContext channelContext : channels) {
					String userid3 = channelContext.getUserid();
					if (!userId.equals(userid3)) {
						userContext = (ImSessionContext) channelContext.getAttribute();
						channelUser = userContext.getClient().getUser();
						if (channelUser != null) {
							// 对方用户也测试过
							if (channelUser.getGender() != gender && channelUser.getYwScore() != null) {
								matching = Coast.getAccuracy(compreAttr, gender, charm, ywScore, qgScore, xnScore,yzScore, mlScore, channelUser);
								//种梨消息在判断 匹配度 是否小于用户设定的匹配度
								if(chatBody.getFlag() == 1 && matching < chatBody.getPearMatching()) {
									chatBody.setEnough(1);
								}
								chatBody.setMatching(matching);
							}else {
								chatBody.setMatching(0);
								if(chatBody.getFlag() == 1) {
									chatBody.setEnough(1);
								}
							}
						}
						chatBody.setIsSelf(0);
					}else {
						userContext = (ImSessionContext) channelContext.getAttribute();
						channelUser = userContext.getClient().getUser();
						
						chatBody.setIsSelf(1);
						chatBody.setMatching(0);
					}
					if(chatBody.getFlag() == 2) {
						long sendUserId =  Long.parseLong(channelContext.getUserid());
						if(sendUserId == userId2) {
								chatBody.setReceiveFlag(1);
						}else if(sendUserId == moduleId2) {
								chatBody.setReceiveFlag(2);
								//发梨用户在线，此时不用管它，自动会弹出效果
								existsSendPearUser = true;
						}else {
								chatBody.setReceiveFlag(0);
						}
					}
					ImPacket chatPacket = new ImPacket(Command.COMMAND_CHAT_REQ,new RespBody(Command.COMMAND_CHAT_REQ,chatBody).toByte());
					send(channelContext, chatPacket);
					
				
					log.info("发送消息用户："+channelUser.getNickName()+",userId:"+channelUser.getId()+",内容："+chatBody.toJsonString());
				}
			} else {
				if(chatBody.getFlag() == 1) {
					chatBody.setEnough(1);
				}
				// 没有测试时向所有群里的用户发送
				for (ChannelContext channelContext : channels) {
					log.info("no test sendUser:" + channelContext.getUserid());
					if (!userId.equals(channelContext.getUserid())) {
						chatBody.setIsSelf(0);
					}else {
						chatBody.setIsSelf(1);
					}
					if(chatBody.getFlag() == 2) {
						long sendUserId =  Long.parseLong(channelContext.getUserid());
						if(sendUserId == userId2) {
								chatBody.setReceiveFlag(1);
						}else if(sendUserId == moduleId2) {
								//发梨用户在线，此时不用管它，自动会弹出效果
								existsSendPearUser = true;
								chatBody.setReceiveFlag(2);
						}else {
								chatBody.setReceiveFlag(0);
						}
					}
					ImPacket chatPacket = new ImPacket(Command.COMMAND_CHAT_REQ,new RespBody(Command.COMMAND_CHAT_REQ,chatBody).toByte());
					send(channelContext, chatPacket);
					
					userContext = (ImSessionContext) channelContext.getAttribute();
					channelUser = userContext.getClient().getUser();
					log.info("发送消息用户："+channelUser.getNickName()+",userId:"+channelUser.getId()+",内容："+chatBody.toJsonString());
				
				}
			}
			
			if(!existsSendPearUser) {
				if(chatBody.getFlag() == 2) {
					try {
						double score = System.currentTimeMillis();
						//当不在线时需要查查被收的信息
						String key = moduleId2 +":" + chatBody.getShopId() + ":closed";
						log.info("缓存键:"+key);
						JedisTemplate.me().setString(key +":1", chatBody.toJsonString(),3600);
						JedisTemplate.me().addWithSortedSet(key, score, chatBody.toJsonString());
						JedisTemplate.me().expire(key, 60 *60 * 24 * 30 );
					} catch (Exception e) {
						log.error("设置我种的梨被接收异常chatBody:"+chatBody.toJsonString(),e);
					}
				}
			}
			
		}
	}

	/**
	 * 商家发布优惠券了手机APP 立马收到消息 功能描述：[发送到群组(所有不同协议端)]--向商家发送 创建者：WChao 创建时间: 2017年9月21日
	 * 下午3:26:57
	 * 
	 * @param groupContext
	 * @param group
	 * @param packet
	 *
	 */
	public static void sendToShopUserGroup(ChannelContext orignChannelContext, String group, ChatBody chatBody) {
		GroupContext groupContext = orignChannelContext.getGroupContext();
		// 判断该组是不是有用户
		SetWithLock<ChannelContext> withLockChannels = Aio.getChannelContextsByGroup(groupContext, group);
		if (withLockChannels == null)
			return;
		Set<ChannelContext> channels = withLockChannels.getObj();
		if (channels.size() == 0) {
			log.info("channels用户数量0:");
			return;
		}
		log.info("channels用户数量:" + channels.size());
		chatBody.setShopId(Long.parseLong(group));
		chatBody.setType(null);
		log.info("聊天信息：" + chatBody.toString());
		// 设置消息类型
		Command commandChatReq = Command.COMMAND_CHAT_REQ;
		chatBody.setCmd(commandChatReq.getNumber());
		for (ChannelContext channelContext : channels) {
			log.info("shop sendUser:" + channelContext.getUserid());
			ImPacket chatPacket = new ImPacket(Command.COMMAND_CHAT_REQ,new RespBody(Command.COMMAND_CHAT_REQ,chatBody).toByte());
			send(channelContext, chatPacket);
		}

	}
	
	
	
}
